#include "EleAndMagScence.h"
#include <cmath>
#include <QtMath>
#include <QGuiApplication>
#include <QResizeEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QPaintEvent>
#include <QPainter>
#include <QPainterPath>
#include <QPoint>
#include <Calculate.h>

EleAndMagScence::EleAndMagScence(QWidget *parent) : QWidget(parent)
{

    isInward = true;
    isMoving = false;
    LineUp = true;


    this->isDraw = false;

    vs = 3 * 1e6;
    vd = 0;
    cmr = 1.758 * pow(10, 11);
    isPost = false;
    isOut = false;
    times = 0;
    b = 0.06;
    dt = 0;
    e = 90000;
    isUp = true;
    calcPoints(0, 0, -81, 90, -100, 100);

}

void EleAndMagScence::paintEvent(QPaintEvent *event)
{

    event->accept();
    QPainter painter(this);

    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing);

    //设置窗口
    mySetWindow(painter, 100, 100, 200, 200);

    //绘图
    myDraw(painter);


    //绘制粒子
    myDrawPath(painter, -81, 90, -100, 100);

    QPen pen;
    pen.setWidthF(0.7);
    painter.setPen(pen);
    //绘制粒子轨迹
    if (times >= 2) {
        for (int i = 2; i < times; ++i) {
            painter.drawPoint(data[i - 2]);
        }
    }
    this->isDraw = false;

}

void EleAndMagScence::myDraw(QPainter &painter)
{

    //画场景标题
    QFont font;
    font.setFamily("隶书");
    font.setPointSize(8);
    font.setPixelSize(12);
    painter.setFont(font);
    painter.setPen(QColor(235,51,36));
    painter.drawText(QRectF(-80,-110,160,40),Qt::AlignCenter, "粒子在电磁场中的运动");

    QPen pen;
    //画坐标轴
    if (true) {
        pen.setWidth(0);
        pen.setStyle(Qt::SolidLine);
        QColor color;
        color.setAlpha(50); //设置背景透明度
        pen.setColor(color);
        painter.setPen(pen);
        int x1 = 0;
        int x2 = 0;
        int y1 = 80;
        int y2 = -80;
        painter.drawLine(x1, y1, x2, y2);//箭身
        double arrowEndX1, arrowEndY1;//箭头端点1
        double arrowEndX2, arrowEndY2;//箭头端点2
        double arrowLength = 5;       // 箭头长度
        arrowEndX1 = x2 - arrowLength * 0.5;
        arrowEndY1 = y2 + arrowLength * sqrt(3)/2;
        arrowEndX2 = x2 + arrowLength * 0.5;
        arrowEndY2 = y2 + arrowLength * sqrt(3)/2;
        painter.drawLine(x2, y2, arrowEndX1, arrowEndY1);//画箭头的第一个角
        painter.drawLine(x2, y2, arrowEndX2, arrowEndY2);//画箭头的第二个角
        QFont font;
        font.setPointSize(1);
        font.setPixelSize(5);
        painter.setFont(font);
        painter.drawText(QRectF(4, -80, 10, 10),Qt::AlignLeft, "y");
        x1 = -100;
        x2 = 100;
        y1 = 0;
        y2 = 0;
        painter.drawLine(x1, y1, x2, y2);//箭身
        arrowEndX1 = x2 - arrowLength * sqrt(3)/2;
        arrowEndY1 = y2 + arrowLength * 0.5;
        arrowEndX2 = x2 - arrowLength * sqrt(3)/2;
        arrowEndY2 = y2 - arrowLength * 0.5;
        painter.drawLine(x2, y2, arrowEndX1, arrowEndY1);//画箭头的第一个角
        painter.drawLine(x2, y2, arrowEndX2, arrowEndY2);//画箭头的第二个角
        painter.drawText(QRectF(98, 2, 10, 10),Qt::AlignLeft, "x");
    }

    //画磁场
    m_paintMag(painter);
    //画电场
    m_paintEle(painter);
}

void EleAndMagScence::mySetWindow(QPainter &painter, int x, int y, int w, int h)
{
    int W=width();
    int H=height();

    //取长和宽的小值
    int side=qMin(W,H);

    //viewport矩形区
    QRect rect((W-side)/2, (H-side)/2,side,side);


    //设置Viewport
    painter.setViewport(rect);

    //设置窗口大小，逻辑坐标
    painter.setWindow(-x, -y, w, h);

}

void EleAndMagScence::m_paintMag(QPainter &painter)
{
    QPen pen;
    pen.setWidth(0);
    pen.setColor(QColor(0,0,0));
    pen.setStyle(Qt::DashLine);
    painter.setPen(pen);

    //画笔
    //painter.drawRect(-90, -78, 180, 160);
    double cx,cy;
    for(cx= -103; cx<= 90; cx++)//-74-->62
    {
        cx+=7.2;
        //if(cx%3==0)
        for(cy= -80; cy<= 75;cy++)
        {
            cy+=7;
            pen.setWidth(0);
            pen.setStyle(Qt::SolidLine);
            QColor color;
            color.setAlpha(50); //设置画笔透明度
            pen.setColor(color);
            painter.setPen(pen);
            //垂直纸面向内
            if(!((cy < -75 ) || (cy > 90 ))) {
                if(isInward)
                {
                    color.setAlpha(100);
                    pen.setColor(color);
                    painter.drawLine(QPointF(cx, cy), QPointF(cx+3, cy+3));
                    painter.drawLine(QPointF(cx+3, cy), QPointF(cx, cy+3));
                }
                //垂直纸面向外
                else
                {
                    pen.setWidth(1);
                    pen.setStyle(Qt::SolidLine);
                    QColor color;
                    color.setAlpha(50); //设置画笔透明度
                    pen.setColor(color);
                    painter.setPen(pen);
                    painter.drawPoint(cx + 2,cy);
                }
            }

        }
    }
}

void EleAndMagScence::m_paintEle(QPainter &painter)
{
    //画电极板(边界线)
    int baseLineTopY = 90;
    int baseLineBottomY = -81;
    int baseLineLeft = -100;
    int baseLineRight = 100;
    QPoint baseTopPointBegin = {baseLineLeft, baseLineTopY};
    QPoint baseTopPointEnd = {baseLineRight, baseLineTopY};
    QPoint baseBottomPointBegin = {baseLineLeft, baseLineBottomY};
    QPoint baseBottomPointEnd = {baseLineRight, baseLineBottomY};
    QPen pen;
    pen.setColor(QColor(0, 0, 0));
    pen.setWidthF(0.5);
    painter.setPen(pen);

    painter.drawLine(baseTopPointBegin, baseTopPointEnd);//Point(-74, 70) to Point(76, 70)//下电极板
    painter.drawLine(baseBottomPointBegin, baseBottomPointEnd);//Point(-74, -65) to Point(76, -65)//上电极板

    if (LineUp) {
        for (int i = -97; i < 0; i += 24) {
            drawArrow(i, 88,i, -78,  painter);
        }
        for (int i = 25; i < 100; i += 24) {
            drawArrow( i, 88, i, -78,painter);
        }
    } else {

        for (int i = -97; i < 0; i += 24) {
            drawArrow(i, -78, i, 88, painter);
        }
        for (int i = 25; i < 100; i += 24) {
            drawArrow(i, -78, i, 88, painter);
        }

    }

}

void EleAndMagScence::drawArrow(double x1, double y1, double x2, double y2, QPainter &painter)
{
    /*
     * 画一个箭头
     */
    if (LineUp) {//如果是向上画箭头，即电场方向朝上
        if (true) {
            //设置画笔
            QPen pen;
            pen.setWidthF(0.5);
            QColor color;
            pen.setColor(color);

            //箭身
            painter.setPen(pen);
            painter.drawLine(x1, y1, x2, y2 + sqrt(3)/2 * 2);
            //箭头
            double arrowEndX1, arrowEndY1;         //箭头端点1
            double arrowEndX2, arrowEndY2;         //箭头端点2
            double arrowLength = 2;                // 箭头长度

            // 求得箭头点 1 的坐标
            arrowEndX1 = x2 - arrowLength * 0.5;
            arrowEndY1 = y2 + arrowLength * sqrt(3)/2;

            // 求得箭头点 2 的坐标
            arrowEndX2 = x2 + arrowLength * 0.5;
            arrowEndY2 = y2 + arrowLength * sqrt(3)/2;

            //画实体三角形
            QPoint points[] = {
                QPoint(x2, y2),
                QPoint(arrowEndX1, arrowEndY1),
                QPoint(arrowEndX2, arrowEndY2)
            };
            QBrush brush;
            brush.setStyle(Qt::SolidPattern);
            painter.setBrush(brush);
            painter.drawPolygon(points, 3);

        } else {//如果例子运动则标明电极板
            //画正
            x1 += 7;
            y1 -= 12;
            y2 += 17;
            painter.drawLine(x1 - 5, y1 + 20, x1 - 5, y1 + 14);//竖
            painter.drawLine(x1 - 8, y1 + 17, x1 - 2, y1 + 17);//横
            //画负
            painter.drawLine(x1 - 8, y2 - 17, x1 - 2, y2 - 17);//横
        }
    } else {//电场方向朝下
        if (true) {
            //设置画笔
            QPen pen;
            pen.setWidthF(0.5);

            //箭身
            painter.setPen(pen);
            painter.drawLine(x1, y1, x2, y2 - sqrt(3)/2 * 2);

            //箭头
            double arrowEndX1, arrowEndY1;//箭头端点1
            double arrowEndX2, arrowEndY2;//箭头端点2
            double arrowLength = 2;      // 箭头长度

            // 求得箭头点 1 的坐标
            arrowEndX1 = x2 - arrowLength * 0.5;
            arrowEndY1 = y2 - arrowLength * sqrt(3)/2;

            // 求得箭头点 2 的坐标
            arrowEndX2 = x2 + arrowLength * 0.5;
            arrowEndY2 = y2 - arrowLength * sqrt(3)/2;

            //画实体三角形
            QPoint points[] = {
                QPoint(x2, y2),
                QPoint(arrowEndX1, arrowEndY1),
                QPoint(arrowEndX2, arrowEndY2)
            };
            QBrush brush;
            brush.setStyle(Qt::SolidPattern);
            painter.setBrush(brush);
            painter.drawPolygon(points, 3);
        } else {//如果例子运动则标明电极板
            //画正
            x1 += 7;
            y1 += 17;
            y2 -= 12;
            painter.drawLine(x1 - 5, y1 - 20, x1 - 5, y1 - 14);//竖
            painter.drawLine(x1 - 8, y1 - 17, x1 - 2, y1 - 17);//横
            //画负
            painter.drawLine(x1 - 8, y2 + 17, x1 - 2, y2 + 17);//横
        }
    }


}

void EleAndMagScence::myDrawPath(QPainter &painter, qreal top, qreal bottom, qreal left, qreal right)
{
    QBrush brush;
    painter.setBrush(brush);
    qreal beginX = 0;
    qreal beginY = 0;
    if (this->isDraw) {
        if (this->isPost) {//如果是正电小球
            if (times < data.size() &&  data[times].x() >= left && data[times].x() <= right
                    && data[times].y() <= bottom && data[times].y() >= top) {
                painter.drawLine(QPointF(data[times].x() - 1, data[times].y()), QPointF(data[times].x() + 1, data[times].y()));
                painter.drawLine(QPointF(data[times].x(), data[times].y() + 1), QPointF(data[times].x(), data[times].y() - 1));
                painter.drawEllipse(data[times], 2, 2);
                times++;
            } else {
                isRepaint = true;
                times = 0;
                isDraw = false;
            }
        } else {//如果是负电小球
            if (times < data.size() &&  data[times].x() >= left && data[times].x() <= right
                    && data[times].y() <= bottom && data[times].y() >= top) {
                painter.drawLine(QPointF(data[times].x() - 1, data[times].y()), QPointF(data[times].x() + 1, data[times].y()));
                painter.drawEllipse(data[times], 2, 2);
                times++;
            } else {
                isRepaint = true;
                times = 0;
                isDraw = false;
            }
        }
    } else {
        if (times >= 1) {//如果粒子已经在运动,该if分支防止暂停时，拖拉窗口重绘导致的小球消失问题
            if (this->isPost) {//如果是正电小球
                if (times - 1 < data.size() &&  data[times - 1].x() >= left && data[times - 1].x() <= right
                        && data[times - 1].y() <= bottom && data[times - 1].y() >= top) {
                    painter.drawLine(QPointF(data[times - 1].x() - 1, data[times - 1].y()), QPointF(data[times -1].x() + 1, data[times - 1].y()));
                    painter.drawLine(QPointF(data[times - 1].x(), data[times - 1].y() + 1), QPointF(data[times - 1].x(), data[times - 1].y() - 1));
                    painter.drawEllipse(data[times - 1], 2, 2);
                    this->isDraw = false;
                } else {
                    times = 0;
                    isDraw = false;
                }
            } else {//如果是负电小球
                if (times - 1 < data.size() &&  data[times - 1].x() >= left && data[times - 1].x() <= right
                        && data[times - 1].y() <= bottom && data[times - 1].y() >= top) {
                    painter.drawLine(QPointF(data[times - 1].x() - 1, data[times - 1].y()), QPointF(data[times - 1].x() + 1, data[times - 1].y()));
                    painter.drawEllipse(data[times - 1], 2, 2);
                    this->isDraw = false;
                } else {
                    times = 0;
                    isDraw = false;
                }
            }
        } else {//绘制初始位置的小球
            if (this->isPost) {//如果是正电小球
                painter.drawLine(QPointF(beginX - 1, beginY), QPointF(beginX + 1, beginY));
                painter.drawLine(QPointF(beginX, beginY + 1), QPointF(beginX, beginY - 1));
                painter.drawEllipse(QPointF(beginX, beginY), 2, 2);
                isDraw = false;
            } else {//如果是负电小球
                painter.drawLine(QPointF(beginX - 1, beginY), QPointF(beginX + 1, beginY));
                painter.drawEllipse(QPointF(beginX, beginY), 2, 2);
                isDraw = false;
            }
        }
    }

}

void EleAndMagScence::calcPoints(qreal startX, qreal startY, qreal top, qreal bottom, qreal left, qreal right)
{
    QPointF begin = {startX, startY};
    data.push_back(begin);
    QPointF particle = begin;

    while (particle.x() >= left && particle.x() <= right && particle.y() <= bottom && particle.y() >= top) {
        dt += 1;

        particle.setX(pow(10, 4.7) * inEleAndMagCalX(pow(10, -11) * dt, this->vs, this->cmr, this->isPost, this->e, this->isUp, this->b, this->isOut));
        particle.setY(pow(10, 4.7) * -inEleAndMagCalY(pow(10, -11) * dt, this->vs, this->cmr, this->isPost, this->e, this->isUp, this->b, this->isOut));

        data.push_back(particle);

        if (dt * (1e-11) * cmr * b >= 2 * M_PI && this->e == 0) {
            break;
        }
        if (dt >= 1000) {
            break;
        }
    }
}


